                            CLASSES

class iden ( op-param-list op-decl)    class definition
  {                                    where op-param-list is an
    iden ( op-param-list ) block       optional parameter list, op-decl
  } ;                                  is an optional list of local
                                       variables with the form ; iden-list
                                       and block consists of one or more
                                       statements enclosed by braces

                                       Example

                                       class queue (;rep) {
                                        queue() {rep = [];}
                                        enqueue(x) {rep = rep conc [x];}
                                        dequeue(;y) {y = hd rep;
                                                     rep = tl rep;
                                                     return y;}};

                             INHERITANCE

class iden1 ( ... ) : iden2             where iden2 is the superclass name
  { ...
                                        Example

                                        class deque (;rep) : queue {
                                         ...


A class is defined by giving the class name, followed by an
enumeration of instance variables in the form of a
parameter list, followed by a collection of function definitions
(also called methods). Classes, contrary to C++, may only contain
functions.

In order to motivate the definition and usage of a class, let us first
define a simple queue. It does not matter what type of item the queue
contains; we will assume a queue of integers. In the specification
below, the state component q (a global variable) represents the queue
as a sequence, which is initialized as the empty sequence.

q=[];
enqueue(x) {q=q conc [x];};
dequeue(;x) {x=hd q;q=tl q;return x;};
empty() {return q==[];};
length() {return len q;};

A typical sequence of operations is:

? enqueue(3);

? enqueue(5);

? length();
 2

? dequeue();
 3

? empty();
 false

? dequeue();
 5

? empty();
 true

There are drawbacks to this approach. Only one queue is available, and
its representation is completely exposed. The problem can be solved by
defining a queue class.

class queue(rep) {

enqueue(x) {rep=rep conc [x];}
dequeue(;y) {y=hd rep;rep=tl rep; return y;}
empty() {return rep==[];}
length() {return len rep;}};

The coding is very similar except now the state component (rep) is local
and is hidden inside the class definition. The representation is
initialized from the outside and may only be changed indirectly by
invoking either the enqueue or dequeue operation. The analogous sequence
of operations is:

? q=new queue([]);

? q.enqueue(3);

? q.enqueue(5);

? q.length;                    or q.length();
 2

? q.dequeue;                   or q.dequeue();
 3

? q.empty;                     or q.empty();
 false

? q.dequeue;                   or q.dequeue();
 5

? q.empty;                     or q.empty();
 true

? q;
 object              this shows the printed representation of an object

A second queue may be instantiated by using the new operation again.

p=new queue([]);

and an arbitrary number of queues may be created in this way.

An example of a priority queue follows.

class pqueue(rep) {

 insrt(x,y) {if(y == []) {rep = [x]; return rep;} else
                     if(x < hd y) {rep = [x] conc y;return rep;} else
                     {rep = [hd y] conc insrt(x,tl y);
                     return rep;}}

 insert(x) {rep = insrt(x,rep); return rep;}
 remove(;x) { if(rep == []) return "queue empty";
                  x = hd rep; rep = tl rep; return x;} };


The last statement in the insert function returns the value of rep
so that the user can see that the items are inserted in sorted
order.Alternatively, the string "ok" could be returned. Note the
declaration of the local variable x in the header of the remove
function. The following sequence of operations show calls to
the insert and remove functions:

? q= new pqueue([]);

? q.insert(3);
 [3]
? q.insert(2);
 [2,3]
? q.insert(9);
 [2,3,9]
? q.insert(7);
 [2,3,7,9]
? q.remove;
 2
? q.remove;
 3
? q.remove;
 7
? q.remove;
 9
? q.remove;
 queue empty

CLASS CONSTRUCTORS

When a class constructor is defined by the user, by declaring a method
with the same name as the class, the corresponding class object will
be initialized automatically when it is instantiated. Taking the queue
example again:

class queue(;rep) {

queue() {rep=[];}
enqueue(x) {rep = rep conc [x];}
dequeue(;y) {y = hd rep; rep = tl rep; return y;}};

An instantiation for this class would have the syntax

iden = new queue();

where iden represents the name of the instantiated object.

Note that rep is defined as a local variable of the class, and that
the first method, named queue, initializes rep to the empty sequence.
When an object is instantiated, i.e. q = new queue(), the rep of that
object will be initialized.


INHERITANCE

A class can inherit instance variables and operations from another
class, called the superclass (or base class). The inheriting class
is called the subclass (or derived class). Suppose that we first
define a queue class:

class queue(;rep) {
 queue() {rep=[];}
 insert(x) {rep=rep conc [x];}
 remove(;y) {y=hd rep;rep=tl rep; return y;}
 empty() {return rep==[];}};

The characteristics of the queue is that items are inserted at one
end and removed from the other end. The queue is represented by a
sequence which is initialized by the empty sequence. Suppose we wish
to define a deque by specializing the operations which are already
provided by the queue. A deque is characterized by allowing insertions
and removals to be performed at either end. We can obtain a deque class
by defining it to be a subclass of queue:

class deque (;rep) : queue {
 deque() {rep=[];}
 insert_front(x) {rep=[x] conc rep;}
 remove_rear(;y) {y=hd (last rep);rep=butlast rep;return y;}
 empty(;x) {if(rep==[]) return "yes";}};

Since insertions to and removals from the queue were made from the
rear and front respectively, we define two new operations insert_front
and remove_rear. So the new class deque inherits the operations insert
and remove from queue, its superclass and defines the two new operations.
The syntax ": queue" which appears in the header defines queue as the
superclass. Since the operation empty has the same name as an operation
in the super class, the new definition of empty supercedes the previous
one.

Consider the following class definitions.

class rec (;value) {
 rec() {value=0;}
 get() {return value;}};

class newrec () : rec {
 newrec() {value=0;}
 get() {return value;}
 setval(x) {value=x;}};

Class rec has the instance variable value which is set to 0 by the
class constructor. The class newrec defines no instance variables itself
but inherits value from its superclass. Value is also initialized by
the class constructor of rec.
